/*
 * @Author: 0x9DEFA478
 * @Date: 2023-02-26 20:25:27
 * @LastEditTime: 2023-03-13 21:58:19
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "PinAssignment.h"
#include "FunctionInfo.h"
#include "PinInfo.h"
#include <QFile>
#include <QFileInfo>
#include <math.h>




template<typename T>
static std::vector<T> QVectorToStdVector(QVector<T> qv){
  qsizetype count;

  count=qv.count();
  std::vector<T> r(count);

  for(qsizetype i=0;i<count;i++){
    r[i]=qv[i];
  }
  
  return r;
}

template<typename T>
static QVector<T> StdVectorToQVector(std::vector<T> v){
  qsizetype count;

  count=v.size();
  QVector<T> r;

  for(qsizetype i=0;i<count;i++){
    r<<v[i];
  }
  
  return r;
}




class PinDesc{
  public:


    enum class PinType:int{
      NC=(int)PinAssignment::ColorIndex::NC,
      GND=(int)PinAssignment::ColorIndex::GND,
      Power=(int)PinAssignment::ColorIndex::Power,
      Sys=(int)PinAssignment::ColorIndex::Sys,
      IO=(int)PinAssignment::ColorIndex::IO_NoFunction,
      Max=(int)PinAssignment::ColorIndex::Max
    };

    
    static PinType StringToType(QString& s);
    static PinType StringToType(QString&& s){return StringToType(s);}

    int Index;
    int X;
    int Y;
    PinType Type;
    QString Name;
    QStringList Functions;

    PinDesc();
    ~PinDesc();
};

PinDesc::PinDesc(){
  Index=-1;
  X=-1;
  Y=-1;
  Type=PinType::NC;
  Name="NC";
  Functions.clear();
}

PinDesc::~PinDesc(){

}

PinDesc::PinType PinDesc::StringToType(QString& s){
  if(0==s.compare("IO")){
    return PinType::IO;
  }else if(0==s.compare("Power")){
    return PinType::Power;
  }else if(0==s.compare("GND")){
    return PinType::GND;
  }else if(0==s.compare("Sys")){
    return PinType::Sys;
  }else if(0==s.compare("NC")){
    return PinType::NC;
  }

  return PinType::Max;
}




class PA_info:public PinAbstract::PinInfo{
  
  private:
    void PA_info_Construct(int index,int X,int Y,std::string& name,PinAssignment* pa);
  public:
    PA_info(int index,int X,int Y,std::string& name,PinAssignment* pa);
    PA_info(int index,int X,int Y,std::string name,PinAssignment* pa);
    virtual ~PA_info(){};

    void SetFunctionIndex(int Index);

    PinDesc::PinType Type(){return type;}
    void SetType(PinDesc::PinType type){this->type=type;}

    int X(){return x;}
    int Y(){return y;}
    
    bool IsHighLight(){return isHighLight;}
    void SetIsHighLight(bool isHighLight){this->isHighLight=isHighLight;}

  private:
    PinAssignment* pa;
    PinDesc::PinType type;
    bool isHighLight;
    int x;
    int y;

};

void PA_info::PA_info_Construct(int index,int X,int Y,std::string& name,PinAssignment* pa){
  this->pa=pa;
  type=PinDesc::PinType::NC;
  isHighLight=false;
  x=X;
  y=Y;

  Q_UNUSED(index);
  Q_UNUSED(name);
}

PA_info::PA_info(int index,int X,int Y,std::string& name,PinAssignment* pa):PinAbstract::PinInfo(index,name){
  PA_info_Construct(index,X,Y,name,pa);
}

PA_info::PA_info(int index,int X,int Y,std::string name,PinAssignment* pa):PinAbstract::PinInfo(index,name){
  PA_info_Construct(index,X,Y,name,pa);
}

void PA_info::SetFunctionIndex(int Index){
  PinAbstract::PinInfo::SetFunctionIndex(Index);

  this->pa->pPinFunctionChange(this->X(),this->Y(),Index);
}

class PA_func:public PinAbstract::FunctionInfo{
  public:

    PA_func(int index,std::string& name);
    PA_func(int index,std::string name);
    virtual ~PA_func(){};

    void SetPinIndex(int Index);

    void AddPin(PA_info* pin);

};

PA_func::PA_func(int index,std::string& name):PinAbstract::FunctionInfo(index,name){
}
PA_func::PA_func(int index,std::string name):PinAbstract::FunctionInfo(index,name){
}

void PA_func::SetPinIndex(int Index){
  PinAbstract::FunctionInfo::SetPinIndex(Index);
}

void PA_func::AddPin(PA_info* pin){

  std::vector<PinAbstract::PinInfo*> infos=FunctionObjects();
  QVector<PinAbstract::PinInfo*> qinfos=StdVectorToQVector(infos);

  qinfos.append(pin);

  infos=QVectorToStdVector(qinfos);

  SetFunctionObjects(infos);

}




static void IndexToXY_LQFP(int Index,int W,int H,int* X,int* Y){

  if(Index<=H){
    X[0]=0;
    Y[0]=Index;
  }else if((Index>H)&&(Index<=(H+W))){
    X[0]=Index-H;
    Y[0]=H+1;
  }else if((Index>(H+W))&&(Index<=(H*2+W))){
    X[0]=W+1;
    Y[0]=H+1-Index+H+W;//(H+1)-(Index-(H+W))
  }else{
    X[0]=H*2+W*2+1-Index;//W+1-(Index-(H*2+W))
    Y[0]=0;
  }

}

static bool BGAIndexToXY(QString& index,int* X,int* Y){
  bool r;
  qsizetype length;
  char c;
  int i;

  length=index.length();
  if(length<2){
    return false;
  }

  QByteArray b=index.toUtf8();

  int y=0;
  for(i=0;i<length;i++){
    c=b[i];
    if((c>='A')&&(c<='Z')){
      if(c>'R'){
        y=y*22+c-'A'-4;
      }else if(c>'P'){
        y=y*22+c-'A'-3;
      }else if(c>'N'){
        y=y*22+c-'A'-2;
      }else if(c>'H'){
        y=y*22+c-'A'-1;
      }else{
        y=y*22+c-'A';
      }
    }else{
      break;
    }
  }
  if(i==0){
    return false;
  }
  Y[0]=y;

  if(i==length){
    return false;
  }

  int x=QString(&index.unicode()[i],length-i).toInt(&r);

  if(r){
    X[0]=x-1;
  }

  return r;
}

static QVector<QString> FuncVectorToQStrings(QVector<PA_func*>& FuncVector){
  qsizetype count=FuncVector.count();

  if(count==0){
    return QVector<QString>();
  }

  QVector<QString> r(count);

  for(qsizetype i=0;i<count;i++){
    r[i]=QString::fromStdString(FuncVector[i]->Name());
  }

  return r;
}

static PA_func* AddFunciton(QVector<PA_func*>& FuncVector,QVector<QString>& FunctionNames,PA_info* info,QString& Function){
  qsizetype count;

  count=FuncVector.count();

  for(qsizetype i=0;i<count;i++){
    if(0==Function.compare(FunctionNames[i])){
      if(i>0){
        FuncVector[i]->AddPin(info);
      }
      return FuncVector[i];
    }
  }
  
  PA_func* r;
  r=new PA_func(count,Function.toStdString());
  r->AddPin(info);
  FuncVector<<r;
  FunctionNames<<QString::fromStdString(r->Name());
  
  return r;
}




PinAssignment::PinAssignment(QObject* parent):QObject(parent){
  PinList=nullptr;
  PinMatrix=nullptr;
  FunList=new QVector<PA_func*>();
  HPAFile=nullptr;
  this->GlobalFunctionIndex=-1;
  // ((QVector<PA_func*>*)FunList)->append(new PA_func(0,std::string(" ")));
  pinAssignment();
}

PinAssignment::~PinAssignment(){

  if(PinList!=nullptr){
    PA_info** List=(PA_info**)PinList;

    for(int i=0;i<PinListSize;i++){
      PA_info* pa=List[i];
      if(pa!=nullptr){
        delete List[i];
      }
    }
    
    delete[] List;
  }

  if(PinMatrix!=nullptr){
    delete[] (PA_info**)PinMatrix;
  }

  for(int i=0;i<((QVector<PA_func*>*)FunList)->count();i++){
    delete ((QVector<PA_func*>*)FunList)[0][i];
  }

  delete (QVector<PA_func*>*)FunList;

  if(HPAFile!=nullptr){
    delete[] HPAFile;
  }

}




void PinAssignment::pinAssignment(){

  Palette[(int)ColorIndex::NC]=QColor(0xFF,0xFF,0xFF);
  Palette[(int)ColorIndex::GND]=QColor(0x88,0xCC,0xFF);
  Palette[(int)ColorIndex::Power]=QColor(0xFF,0x88,0x88);
  Palette[(int)ColorIndex::Sys]=QColor(0x99,0x99,0x00);
  Palette[(int)ColorIndex::IO_NoFunction]=QColor(0xFF,0xFF,0xFF);
  Palette[(int)ColorIndex::IO_Selectable]=QColor(0x00,0xFF,0x33);
  Palette[(int)ColorIndex::IO_Function]=QColor(0x00,0x88,0xFF);
  Palette[(int)ColorIndex::IO_Conflict]=QColor(0xFF,0x00,0x00);
  Palette[(int)ColorIndex::IO_FunctionConflict]=QColor(0x00,0xCC,0xFF);

}

void PinAssignment::LoadSPA(const QString& Path){
  QString token;

  LoadHPA(Path);


  QFile file(Path);

  if(!file.open(QIODeviceBase::OpenModeFlag::ReadOnly)){
    throw QString(file.errorString().toUtf8().data());
  }
  
  try{

    QTextStream textStream(&file);

    token="PinSelect";
    while(true){
      QString lineStr=textStream.readLine();

      if(lineStr.isNull()){
        throw QString("无效的文件, 选择信息!");
      }

      if(0==QString(lineStr.unicode(),token.length()).compare(token)){

        break;
      }
    }

    QStringList strs;

    token="PinSelect";
    while(true){
      QString lineStr=textStream.readLine();

      if(lineStr.isNull()){
        throw QString("无效的文件, 格式错误!");
      }

      if(0==QString(lineStr.unicode(),token.length()).compare(token)){
        break;
      }

      strs<<lineStr;
    }

    //恢复显示

    for(qsizetype i=0,count=strs.count();i<count;i++){
      bool ok;
      QStringList nums=strs[i].split(' ',Qt::SplitBehaviorFlags::SkipEmptyParts);

      if(nums.count()<3){
        throw QString("错误的保存索引描述!");
      }

      int x=nums[0].toInt(&ok);
      if(!ok){
        throw QString("错误的保存索引描述!(x)");
      }
      int y=nums[1].toInt(&ok);
      if(!ok){
        throw QString("错误的保存索引描述!(y)");
      }
      int index=nums[2].toInt(&ok);
      if(!ok){
        throw QString("错误的保存索引描述!(index)");
      }

      FunctionSelect(x+y*Width,index);

    }
    
  }catch(const QString& s){
    file.close();
    throw s;
  }

  file.close();

}

void PinAssignment::LoadHPA(const QString& Path){
  QString token;
  QString package;
  PinDesc* pinDescs=nullptr;
  int packsize;
  int W;
  int H;

  QFile file(Path);

  if(!file.open(QIODeviceBase::OpenModeFlag::ReadOnly)){
    throw QString(file.errorString().toUtf8().data());
  }
  
  try{

    QTextStream textStream(&file);

    token="Package ";
    while(true){
      QString lineStr=textStream.readLine();

      if(lineStr.isNull()){
        throw QString("无效的文件, 找不到封装信息!");
      }

      if(0==QString(lineStr.unicode(),token.length()).compare(token)){

        package=QString(&lineStr.unicode()[token.length()],lineStr.length()-token.length());

        break;
      }
    }

    token="LQFP";
    if(0==QString(package.unicode(),token.length()).compare(token)){
      bool ok=false;
      
      packsize=QString(&package.unicode()[token.length()],package.length()-token.length()).toInt(&ok);

      if(!ok){
        throw QString("找不到封装尺寸");
      }

      if((packsize%4)!=0){
        throw QString("错误的封装尺寸");
      }

      W=packsize/4+2;
      H=packsize/4+2;

      QStringList strs;

      token="Package";
      while(true){
        QString lineStr=textStream.readLine();

        if(lineStr.isNull()){
          throw QString("无效的文件, 格式错误!");
        }

        if(0==QString(lineStr.unicode(),token.length()).compare(token)){
          break;
        }

        strs<<lineStr;
      }

      //解析引脚信息

      pinDescs=new PinDesc[packsize];

      for(int i=0;i<strs.count();i++){
        QString& pinstr=strs[i];
        bool ok;
        
        QStringList items=pinstr.split(' ',Qt::SplitBehaviorFlags::SkipEmptyParts);

        if(items.count()<3){
          throw QString("无效的引脚描述信息");
        }

        int pinId=items[0].toInt(&ok);

        if(!ok){
          throw QString("无效的引脚编号:"+items[0]);
        }
        if((pinId>packsize)||(pinId<1)){
          throw QString("错误的引脚编号:"+items[0]);
        }

        pinId--;

        PinDesc::PinType pintype=PinDesc::StringToType(items[1]);

        if(pintype==PinDesc::PinType::Max){
          throw QString("错误的引脚类型:"+items[0]);
        }

        if(pinDescs[pinId].Index>-1){
          throw QString("引脚被重复定义:"+items[0]);
        }

        pinDescs[pinId].Type=pintype;
        pinDescs[pinId].Index=pinId;
        IndexToXY_LQFP(pinId+1,packsize/4,packsize/4,&pinDescs[pinId].X,&pinDescs[pinId].Y);
        pinDescs[pinId].Name=items[0]+":"+items[2];

        for(int j=3;j<items.count();j++){
          pinDescs[pinId].Functions<<items[j];
        }
      }

      


    }else{
      token="BGA";
      if(0==QString(package.unicode(),token.length()).compare(token)){
        bool ok=false;
      
        packsize=QString(&package.unicode()[token.length()],package.length()-token.length()).toInt(&ok);

        if(!ok){
          throw QString("找不到封装尺寸");
        }

        int side=(int)sqrt((double)packsize);
        if(((int)pow(side,2))!=packsize){
          throw QString("错误的封装尺寸");
        }

        W=side;
        H=side;

        QStringList strs;

        token="Package";
        while(true){
          QString lineStr=textStream.readLine();

          if(lineStr.isNull()){
            throw QString("无效的文件, 格式错误!");
          }

          if(0==QString(lineStr.unicode(),token.length()).compare(token)){
            break;
          }

          strs<<lineStr;
        }

        //解析引脚信息

        pinDescs=new PinDesc[packsize];

        for(int i=0;i<strs.count();i++){
          QString& pinstr=strs[i];
          
          QStringList items=pinstr.split(' ',Qt::SplitBehaviorFlags::SkipEmptyParts);

          if(items.count()<3){
            throw QString("无效的引脚描述信息");
          }

          int x;
          int y;

          if(!BGAIndexToXY(items[0],&x,&y)){
            throw QString("无效的引脚坐标:"+items[0]);
          }

          if((x>=side)||(y>=side)){
            throw QString("引脚坐标超出范围:"+items[0]);
          }
          if((x<0)||(y<0)){
            throw QString("引脚坐标无效范围:"+items[0]);
          }

          int pinId=y*side+x;

          PinDesc::PinType pintype=PinDesc::StringToType(items[1]);

          if(pintype==PinDesc::PinType::Max){
            throw QString("错误的引脚类型:"+items[0]);
          }

          if(pinDescs[pinId].Index>-1){
            throw QString("引脚被重复定义:"+items[0]);
          }

          pinDescs[pinId].Type=pintype;
          pinDescs[pinId].Index=pinId;
          pinDescs[pinId].X=x;
          pinDescs[pinId].Y=y;
          pinDescs[pinId].Name=items[0]+":"+items[2];

          for(int j=3;j<items.count();j++){
            pinDescs[pinId].Functions<<items[j];
          }

        }


      }else{
        throw QString("不支持的封装");
      }
    }
  }catch(const QString& s){
    file.close();
    if(pinDescs!=nullptr){
      delete[] pinDescs;
    }
    throw s;
  }

  file.close();

  //添加引脚信息

  QVector<PA_func*>& funcList=((QVector<PA_func*>*)FunList)[0];
  QVector<QString> funcList_s=FuncVectorToQStrings(funcList);
  PA_info** Matrix;
  PA_info** List;
  Matrix=new PA_info*[W*H];
  PinMatrix=Matrix;
  List=new PA_info*[packsize];
  PinList=List;
  PinListSize=packsize;

  for(int i=0;i<W*H;i++){
    Matrix[i]=nullptr;
  }

  for(int i=0;i<packsize;i++){
    PinDesc& pd=pinDescs[i];
    QVector<PinAbstract::FunctionInfo*> Functions;

    PA_info* info=new PA_info(i,pd.X,pd.Y,pd.Name.toStdString(),this);
    info->SetType(pd.Type);

    for(qsizetype j=0;j<pd.Functions.count();j++){
      Functions<<(PinAbstract::FunctionInfo*)AddFunciton(funcList,funcList_s,info,pd.Functions[j]);
    }

    info->SetFunctionObjects(QVectorToStdVector(Functions));
    Matrix[pd.X+pd.Y*W]=info;
    List[i]=info;

  }

  Width=W;
  Height=H;

  delete[] pinDescs;

}




void PinAssignment::GetFunctionList(QStringList& FunctionList){
  QVector<PA_func*>* list;
  qsizetype count;

  list=(QVector<PA_func*>*)FunList;
  count=list->count();
  for(qsizetype i=0;i<count;i++){
    FunctionList<<QString::fromStdString(list[0][i]->Name());
  }

}

void PinAssignment::GetPinList(QList<PinInfo>& PinList){
  PA_info** M;

  M=(PA_info**)this->PinMatrix;
  for(int y=0;y<Height;y++){
    for(int x=0;x<Width;x++){
      PA_info* info=M[x+y*Width];
      if(info==nullptr){
        PinList<<PinInfo(-1," ");
        continue;
      }

      QStringList funcList;

      int funcCount=info->FunctionCount();

      for(int i=0;i<funcCount;i++){
        funcList<<QString::fromStdString(info->GetFunctionByIndex(i)->Name());
      }

      PinList<<PinInfo(x+y*Width,QString::fromStdString(info->Name()),funcList);
    }
  }
}

void PinAssignment::AllPinUpdate(){
  PA_info** list;

  list=(PA_info**)PinList;

  for(int i=0;i<PinListSize;i++){
    PA_info& info=list[i][0];
    int x=info.X();
    int y=info.Y();

    if((x<0)||(y<0)){
      continue;
    }

    pPinFunctionChange(info.X(),info.Y(),info.FunctionIndex());
  }
}

void PinAssignment::SetColor(ColorIndex index,int r,int g,int b){
  Palette[(int)index]=QColor(r,g,b);
}

void PinAssignment::HighLightFunction(int GlobalFunctionIndex,bool IsHighLight){

  if(IsHighLight){
    if(GlobalFunctionIndex==this->GlobalFunctionIndex){
      HighLightFunction(GlobalFunctionIndex,false);
      return;
    }
    if(HighLightPins.count()>0){
      HighLightFunction(GlobalFunctionIndex,false);
    }

    this->GlobalFunctionIndex=GlobalFunctionIndex;

    PA_func& func=((QVector<PA_func*>*)FunList)[0][GlobalFunctionIndex][0];

    int count=func.PinCount();

    for(int i=0;i<count;i++){
      PA_info& info=((PA_info*)(func.GetPinInfoByIndex(i)))[0];
      info.SetIsHighLight(true);
      pPinFunctionChange(info.X(),info.Y(),info.FunctionIndex());
      HighLightPins<<info.Index();
    }

  }else{
    
    qsizetype count=HighLightPins.count();

    for(qsizetype i=0;i<count;i++){
      PA_info& info=((PA_info**)PinList)[HighLightPins[i]][0];

      info.SetIsHighLight(false);

      pPinFunctionChange(info.X(),info.Y(),info.FunctionIndex());
    }

    HighLightPins.clear();

    this->GlobalFunctionIndex=-1;
  }

}

void PinAssignment::FunctionSelect(int PinIndex,int FunctionIndex){

  if(PinIndex<0){
    return;
  }

  PA_info* info=((PA_info**)PinMatrix)[PinIndex];

  if(info!=nullptr){
    PinAbstract::PinInfo::SetFunctionIndex(info,FunctionIndex);
  }

}

void PinAssignment::SaveFile(QString& Path){

  QFile file(Path);

  if(!file.open(QIODeviceBase::OpenModeFlag::ReadWrite|QIODeviceBase::OpenModeFlag::Truncate)){
    throw QString(file.errorString().toUtf8().data());
  }

  try{

    file.write((char*)HPAFile,HPAFile_Size);
    file.write(QString("\r\nPinSelect\r\n").toUtf8());

    for(int i=0;i<PinListSize;i++){
      PA_info& info=((PA_info**)PinList)[i][0];
      int index=info.FunctionIndex();

      if(index>=0){
        int x=info.X();
        int y=info.Y();

        QString s=QString::number(x)+" "+QString::number(y)+" "+QString::number(index)+"\r\n";

        file.write(s.toUtf8());
      }

    }

    file.write(QString("PinSelect\r\n").toUtf8());

  }catch(const QString& e){

    file.close();

    throw e;
  }

  file.close();
}

void PinAssignment::LoadFile(const QString& Path){

  QFileInfo fileInfo=QFileInfo(Path);

  QString suffix=fileInfo.suffix().toLower();

  if((suffix.length()>2)&&(suffix.compare("spa")==0)){
    LoadSPA(Path);
  }else{
    LoadHPA(Path);
  }


  QFile file(Path);

  if(!file.open(QIODeviceBase::OpenModeFlag::ReadOnly)){
    throw QString(file.errorString().toUtf8().data());
  }

  QTextStream textStream(&file);
  QStringList Lines;
  QString token;

  token="Package";
  while(true){
    QString lineStr=textStream.readLine();

    if(lineStr.isNull()){
      throw QString("无效的文件, 格式错误!");
    }

    if(0==QString(lineStr.unicode(),token.length()).compare(token)){
      Lines<<lineStr;
      break;
    }
  }
  while(true){
    QString lineStr=textStream.readLine();

    if(lineStr.isNull()){
      throw QString("无效的文件, 格式错误!");
    }

    Lines<<lineStr;
    if(0==QString(lineStr.unicode(),token.length()).compare(token)){
      break;
    }

  }

  QString s="";

  for(qsizetype i=0,count=Lines.count();i<count;i++){
    s+=Lines[i]+"\r\n";
  }

  QByteArray ba=s.toUtf8();


  if((HPAFile_Size=ba.length())>0){

    HPAFile=new unsigned char[ba.length()];
    memcpy(HPAFile,ba.data(),HPAFile_Size);
  }

  file.close();

}

void PinAssignment::pPinFunctionChange(int X,int Y,int Index){
  PinDesc::PinType type;
  QColor color;
  PA_info* info=((PA_info**)PinMatrix)[X+Y*Width];

  if(info==nullptr){
    emit PinFunctionChange(X+Y*Width,PinAssignment::PinStatus(Palette[(int)ColorIndex::NC],Index));
    return;
  }

  type=info->Type();
  
  if(type!=PinDesc::PinType::IO){
    color=Palette[(int)type];
  }else{
    int index;
    if(info->IsHighLight()){
      index=info->FunctionIndex();
      if(index<0){
        color=Palette[(int)ColorIndex::IO_Selectable];
      }else if(this->GlobalFunctionIndex==info->GetFunctionByIndex(index)->Index()){
        color=Palette[(int)ColorIndex::IO_FunctionConflict];
      }else{
        color=Palette[(int)ColorIndex::IO_Conflict];
      }
    }else{
      if(info->FunctionIndex()<0){
        color=Palette[(int)ColorIndex::IO_NoFunction];
      }else{
        color=Palette[(int)ColorIndex::IO_Function];
      }
    }
  }

  PinAssignment::PinStatus status(color,Index);

  emit PinFunctionChange(X+Y*Width,status);
}



